#include "StateGraph.h"
#include "StateBase.h"

//-------------------------------------------------------------------------
CStateGraph::CStateGraph(const CStateDataPtr &pStateData) : CStateBase(pStateData)
{
}

//-------------------------------------------------------------------------
CStateGraph::CStateGraph(const char_t *szName) : CStateBase(szName)
{
}

//-------------------------------------------------------------------------
void CStateGraph::AddState(const CStateBasePtr &pState)
{
	m_pStates.push_back(pState);
}

//-------------------------------------------------------------------------
void CStateGraph::SetInitialState(const CStateBasePtr &pState)
{
	m_pInitialState = pState;
}

//-------------------------------------------------------------------------
void CStateGraph::DoUpdate(CStateResult *pResult)
{
	if(!m_pCurrentState.IsValid())
	{
		m_pCurrentState = m_pInitialState;

		m_pCurrentState->OnEnter(pResult);
	}
	else
	{
		TTransitionList vTriggeredTransitions;

		m_pCurrentState->OnEvualuate(vTriggeredTransitions);

		if(!vTriggeredTransitions.empty())
		{
			pResult->SetTransitions(vTriggeredTransitions);

			m_pCurrentState->OnExit(pResult);
		
			CStateBasePtr pNextState = vTriggeredTransitions.front()->GetNextState();
			
			pNextState->OnEnter(pResult);
			
			CStateGraph *pParentNextState = pNextState->GetParent();
		
			if(pParentNextState)
			{
				pParentNextState->SetCurrentState(pNextState, pResult);
			}
		}
		else
		{
			pResult->AddActions(m_vActions);

			if(m_pCurrentState.IsValid())
			{
				m_pCurrentState->OnUpdate(pResult);
			}
			
			if(pResult->GetResult() == CStateResult::Done)
			{
				m_pCurrentState->OnExit(pResult);
				m_pCurrentState = NULL;
			}
		}
	}
}

//-------------------------------------------------------------------------
void CStateGraph::SetCurrentState(const CStateBasePtr &pState, CStateResult *pStateResult)
{
	if(m_pCurrentState.IsValid())
	{
		if(m_pCurrentState != pState)
		{
			m_pCurrentState->OnExit(pStateResult);
		}
	}
	
	m_pCurrentState = pState;
	
	if(m_pParent)
	{
		CStateGraph *pParent = pState->GetParent();
		m_pParent->SetCurrentState(pParent, pStateResult);
	}
}


DEFINE_RTTI_CLASS( CStateGraph, CStateBase );